package com.example.springboottest.example.recursive;

import java.util.stream.IntStream;

public class RecursiveTest {
    public static void main(String[] args) {
        int num = 5;
        int result = 0;

//        result = iteration(num);

        result = reduce(num);

//        result = commonRecursive(num);

//        result = factorialHelper(1, 5);

        System.out.println("result=\t" + result);

    }

    /**
     * 最简单的迭代方式求积
     *
     * @param num
     * @return
     */
    public static int iteration(int num) {
        int result = 1;
        for (int i = 1; i <= num; i++) {
            result *= i;
        }
        return result;
    }

    /**
     * 归约方式求积
     *
     * @param num
     * @return
     */
    public static int reduce(int num) {
        return IntStream.rangeClosed(3, num).reduce(1, (a, b) -> a * b);
    }

    /**
     * 普通递归方式求积
     *
     * @param num
     * @return
     */
    public static int commonRecursive(int num) {
        return num == 1 ? 1 : num * commonRecursive(num - 1);
    }

    /**
     * 尾–递 递归方式求积,和普通递归的区别在于不会生成多个堆栈，只会有一个堆栈
     * <p>
     * 基本的思想是你可以编写阶乘的一个迭代定义，不过迭代调用发生在函数的最后（所以我们说调用发生在尾部）。
     * 这种新型的迭代调用经过优化后执行的速度快很多。
     * 坏消息是，目前 Java 还不支持这种优化。但是使用相对于传统的递归，“尾–递”可能是更
     * 好的一种方式，因为它为最终实现编译器优化开启了一扇门。很多的现代 JVM 语言，比如 Scala、
     * Groovy 和 Kotlin，都已经支持对这种形式的递归的优化，最终实现的效果和迭代不相上下（它们
     * 的运行速度几乎是相同的）
     *
     * @param acc,
     * @param num
     * @return
     */
    public static int factorialHelper(int acc, int num) {
        return num == 1 ? acc : factorialHelper(acc * num, num - 1);
    }
}
